package xcmg.device.web.warehouse;

import com.alibaba.fastjson.JSON;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import xcmg.device.infra.BasicController;
import xcmg.device.infra.ErrorCode;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.warehouse.WarehouseInboundAddVO;
import xcmg.device.service.vo.warehouse.WarehouseInboundRecordAddVO;
import xcmg.device.service.vo.warehouse.WarehouseInboundRecordBatchAddVO;
import xcmg.device.service.vo.warehouse.WarehouseInboundRecordVO;
import xcmg.device.service.warehouse.WarehouseInboundRecordService;
import xcmg.device.util.RedisConstant;
import yb.ecp.fast.infra.annotation.FastMappingInfo;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.infra.log.LogHelper;
import yb.ecp.fast.infra.util.ListUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/warehouseInboundRecord")
public class WarehouseInboundRecordController extends BasicController{
    @Autowired
    private WarehouseInboundRecordService warehouseInboundRecordService;
    @Autowired
    private RedissonClient redissonClient;

    private static final Object obj = new Object();

    @RequestMapping(value = "/add",method = RequestMethod.POST)
    @ApiOperation(value = "增加入库记录")
    @FastMappingInfo(needLogin = true)
    public ActionResult warehouse(@RequestBody WarehouseInboundRecordBatchAddVO warehouseInboundRecordBatchAddVO)throws Exception{
        if(null == warehouseInboundRecordBatchAddVO || ListUtil.isNullOrEmpty(warehouseInboundRecordBatchAddVO.getRecordList())){
            return actionResult(ErrorCode.IllegalArument);
        }
        String orgId = getOrgId();
        LogHelper.monitor("增加入库记录传参：" + JSON.toJSONString(warehouseInboundRecordBatchAddVO));
        WarehouseInboundRecordAddVO inboundRecord = warehouseInboundRecordBatchAddVO.getRecordList().get(0);
        String businessOrder = inboundRecord.getBusinessOrder();
        if(StringUtils.isEmpty(businessOrder)){
            return actionResult(ErrorCode.AbnormalInNotFound);
        }
        String padInboundBarcodeCacheKey = RedisConstant.RedisKeyContant.PDA_INBOUND_BARCODE_CACHE_KEY+businessOrder;
        RLock lock = redissonClient.getLock(padInboundBarcodeCacheKey);
        boolean isLock;
        try {
            isLock = lock.tryLock(0,RedisConstant.OUT_INBOUND_LOCK_TIME, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            log.error("pda扫码入库获取分布式锁异常{}",e);
            return actionResult(ErrorCode.PdaInboundLockError);
        }
        if(!isLock){
            log.warn("pda扫码入库存在已经执行的任务,无法获取锁，本次不执行");
            return actionResult(ErrorCode.PdaInboundLockError);
        }
        FunctionResult result = new FunctionResult();
        List<WarehouseInboundRecordAddVO> errorList = new ArrayList<>();
        try{
            ErrorCode errorCode = warehouseInboundRecordService.batchAdd(warehouseInboundRecordBatchAddVO, getUserId(), orgId);
            result.setCode(errorCode);
        }catch (Exception e){
            log.error("pda扫码入库异常{}",e);
            WarehouseInboundRecordAddVO recordAddVO = warehouseInboundRecordBatchAddVO.getRecordList().get(getIndex(e.getMessage()));
            recordAddVO.setRemark(getMsg(e.getMessage()));
            errorList.add(recordAddVO);
            for (int i = 0; i < warehouseInboundRecordBatchAddVO.getRecordList().size(); i++) {
                if (i != getIndex(e.getMessage())) {
                    errorList.add(warehouseInboundRecordBatchAddVO.getRecordList().get(i));
                }
            }
            String errorMsg = ErrorCode.Failure.getDesc();
            if(!CollectionUtils.isEmpty(errorList)){
                String remark = errorList.get(0).getRemark();
                if(!StringUtils.isEmpty(remark)){
                    errorMsg = remark;
                }
            }
            result.setCode(ErrorCode.Failure);
            result.setValue(errorList);
            return actionResult(result.getCode(),errorMsg, result.getValue());
        }finally {
            lock.unlock();
        }
        return actionResult(result.getCode(), result.getValue());
    }

    @RequestMapping(value = "/receive",method = RequestMethod.POST)
    @ApiOperation(value = "无条码化入库")
    @FastMappingInfo(needLogin = true)
    public ActionResult receive(@RequestBody WarehouseInboundAddVO inboundAddVO)throws Exception{
        if(null == inboundAddVO || ListUtil.isNullOrEmpty(inboundAddVO.getDetailList())){
            return actionResult(ErrorCode.IllegalArument);
        }
        String businessOrder = inboundAddVO.getHeaderInfo().getBusinessOrder();
        RLock lock = null;
        if(!StringUtils.isEmpty(businessOrder)){//单据编码不为空则进行锁控制，兼容业务
            String noBarcodeInboundBusinessOrderCacheKey = RedisConstant.RedisKeyContant.NOBARCODE_INBOUND_BUSINESSORDER_CACHE_KEY+businessOrder;
            lock = redissonClient.getLock(noBarcodeInboundBusinessOrderCacheKey);
            boolean isLock;
            try {
                isLock = lock.tryLock(0,RedisConstant.OUT_INBOUND_LOCK_TIME, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                log.error("pda扫码入库获取分布式锁异常{}",e);
                return actionResult(ErrorCode.NoBarcodeInboundLockError);
            }
            if(!isLock){
                log.warn("非条码入库存在已经执行的任务,无法获取锁，本次不执行");
                return actionResult(ErrorCode.NoBarcodeInboundLockError);
            }
        }
        FunctionResult result = new FunctionResult();
        try{
            ErrorCode errorCode;
            synchronized (obj) {
                errorCode = warehouseInboundRecordService.receive(inboundAddVO, getUserId(), getOrgId());
            }
            result.setCode(errorCode);
        }catch (Exception e){
            return new ActionResult(ErrorCode.Failure.getCode(), e.getMessage());
        }finally {
            if(lock != null){
                lock.unlock();
            }
        }
        return actionResult(result.getCode(), result.getValue());
    }

    @RequestMapping(value = "/list",method = RequestMethod.POST)
    @ApiOperation("查询入库记录列表")
    @FastMappingInfo(needLogin = true)
    public ActionResult listInboundNote(@RequestBody SearchCommonVO<WarehouseInboundRecordVO> condition)throws Exception{
        WarehouseInboundRecordVO warehouseInboundRecordVO =condition.getFilters();
        if(warehouseInboundRecordVO == null){
            warehouseInboundRecordVO = new WarehouseInboundRecordVO();
        }
        warehouseInboundRecordVO.setOrgId(getOrgId());
        condition.setFilters(warehouseInboundRecordVO);
        PageCommonVO pageCommonVO= warehouseInboundRecordService.list(condition);
        return actionValueResult(pageCommonVO.getPageInfo());
    }

    @RequestMapping(value = "/remove",method = RequestMethod.POST)
    @ApiOperation("入库记录删除")
    @FastMappingInfo(needLogin = true)
    public ActionResult delete(@RequestBody String[] ids){
        if(ids == null || ids.length == 0){
            return actionResult(ErrorCode.IllegalArument);
        }
        return actionResult(warehouseInboundRecordService.remove(Arrays.asList(ids)));
    }

    @RequestMapping(value = "/export",method = RequestMethod.POST)
    @ApiOperation("导出入库记录列表")
    @FastMappingInfo(needLogin = true)
    public void export(@RequestBody String[] ids)throws Exception {
        warehouseInboundRecordService.export(Arrays.asList(ids));
    }

    @RequestMapping(value = "/exportAll",method = RequestMethod.POST)
    @ApiOperation("导出全部入库记录列表")
    @FastMappingInfo(needLogin = true)
    public void exportAll(WarehouseInboundRecordVO condition)throws Exception {
        if(condition == null){
            condition = new WarehouseInboundRecordVO();
        }
        condition.setOrgId(getOrgId());
        warehouseInboundRecordService.exportAll(condition);
    }

    @RequestMapping(value = "/findAlreadyInboundNum",method = RequestMethod.POST)
    @ApiOperation("获取入库业务单已入库和未入库的数量")
    @FastMappingInfo(needLogin = true)
    public ActionResult findAlreadyInboundNum(String businessOrder)throws Exception{
        return actionValueResult(warehouseInboundRecordService.findAlreadyInboundNum(businessOrder, getOrgId()));
    }

    @RequestMapping(value = "/findAlreadyInboundList",method = RequestMethod.POST)
    @ApiOperation("获取入库业务单已入库和未入库的列表")
    @FastMappingInfo(needLogin = true)
    public ActionResult findAlreadyInboundList(String businessOrder, Integer state)throws Exception{
        return actionValueResult(warehouseInboundRecordService.findAlreadyInboundList(businessOrder, state, getOrgId()));
    }

    private Integer getIndex(String msg){
        try {
            if(!msg.startsWith("index&&")){
                return 0;
            }
            String[] str = msg.split("&&");
            return new Integer(str[1]);
        }catch (Exception e){
            return 0;
        }
    }

    private String getMsg(String msg){
        try {
            if(!msg.startsWith("index&&")){
                return msg;
            }
            String[] str = msg.split("&&");
            return str[2];
        }catch (Exception e){
            return msg;
        }
    }
}
